#pragma once

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QMap>
#include <functional>
#include "../nlohmann/json.hpp"

class HttpUtil : public QObject {
    Q_OBJECT

public:
    using json = nlohmann::json;
    using HandlerFunc = std::function<json(const QString &path, const QMap<QString, QString> &query, const json &body)>;

    enum class Method { GET, POST, PUT, DELETE };

    static HttpUtil &getInstance();

    void init();

    void startServer(int port);

    void registerHandler(Method method, const QString &pathPattern, HandlerFunc handler);

    static void addRoute(Method method, const QString &pathPattern, HandlerFunc handler);

private:
    explicit HttpUtil(QObject *parent = nullptr);

    void handleNewConnection();

    void handleReadyRead(QTcpSocket *socket);

    void loadConfig();

    QString extractMethod(const QString &requestLine);

    QString extractPath(const QString &requestLine);

    QMap<QString, QString> extractQuery(const QString &path);

    QString normalizePath(const QString &path);

    QTcpServer *server = nullptr;
    bool initialized = false;
    int configuredPort = 8080;
    bool autoStart = true;

    struct RouteKey {
        Method method;
        QString pathPattern;

        bool operator<(const RouteKey &other) const {
            return std::tie(method, pathPattern) < std::tie(other.method, other.pathPattern);
        }
    };

    QMap<RouteKey, HandlerFunc> handlers;
};
